package com.ruoyi.slope.api.service.impl;

import com.ruoyi.slope.api.constant.MonitorTypeEnum;
import com.ruoyi.slope.api.service.SlopeDataApiService;
import com.ruoyi.slope.data.crack.domain.SlopeCrackData;
import com.ruoyi.slope.data.crack.mapper.SlopeCrackDataMapper;
import com.ruoyi.slope.data.crack.service.ISlopeCrackDataService;
import com.ruoyi.slope.data.fencenet.domain.SlopeFencenetData;
import com.ruoyi.slope.data.fencenet.service.ISlopeFencenetDataService;
import com.ruoyi.slope.data.soil.domain.SlopeSoilData;
import com.ruoyi.slope.data.soil.service.ISlopeSoilDataService;
import com.ruoyi.slope.data.weather.domain.SlopeWeatherData;
import com.ruoyi.slope.data.weather.service.ISlopeWeatherDataService;
import com.ruoyi.slope.device.deviceInfo.domain.SlopeDeviceInfo;
import com.ruoyi.slope.device.deviceInfo.service.ISlopeDeviceInfoService;
import com.ruoyi.slope.device.deviceInfo.service.impl.SlopeDeviceInfoServiceImpl;
import com.ruoyi.slope.info.domain.SlopeInfo;
import com.ruoyi.slope.info.service.impl.SlopeInfoServiceImpl;
import com.ruoyi.slope.monitorPoints.domain.SlopeMonitorpoints;
import com.ruoyi.slope.monitorPoints.service.ISlopeMonitorpointsService;
import com.ruoyi.slope.warning.info.domain.SlopeWarningInfo;
import com.ruoyi.slope.warning.info.service.impl.SlopeWarningInfoServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;

/**
 * 边坡监测数据 API 服务实现
 * 根据 monitorType 获取对应 DTO 数据并组装接口返回格式
 */
@Service
@RequiredArgsConstructor
public class SlopeDataApiServiceImpl implements SlopeDataApiService {

    private final ISlopeMonitorpointsService slopeMonitorpointsService;
    private final ISlopeCrackDataService slopeCrackDataService;
    private final ISlopeWeatherDataService slopeWeatherDataService;
    private final ISlopeSoilDataService slopeSoilDataService;
    private final ISlopeFencenetDataService slopeFencenetDataService;
    private final ISlopeDeviceInfoService  slopeDeviceInfoService;
    private final SlopeInfoServiceImpl slopeInfoServiceImpl;
    private final SlopeWarningInfoServiceImpl slopeWarningInfoServiceImpl;
    private final SlopeDeviceInfoServiceImpl slopeDeviceInfoServiceImpl;
    private final SlopeCrackDataMapper slopeCrackDataMapper;

    private Map<String, DataFetcher> monitorTypeMap;
    private Map<String, DataFetcher> monitorTypeSetMap;

    @PostConstruct
    public void init1() {
        monitorTypeMap = new HashMap<>();
        for (MonitorTypeEnum typeEnum : MonitorTypeEnum.values()) {
            switch (typeEnum) {
                case CRACK:
                    monitorTypeMap.put(typeEnum.getMonitorType(), slopeCrackDataService::getLatestCrackData);
                    break;
                case STRUCTURE_TILT:
                    monitorTypeMap.put(typeEnum.getMonitorType(), slopeCrackDataService::getLatestTiltData);
                    break;
                case RAINFALL:
                    monitorTypeMap.put(typeEnum.getMonitorType(), slopeWeatherDataService::getLatestRainfall);
                    break;
                case TEMPERATURE:
                    monitorTypeMap.put(typeEnum.getMonitorType(), slopeWeatherDataService::getLatestTemperature);
                    break;
                case ACCELERATION:
                    monitorTypeMap.put(typeEnum.getMonitorType(), slopeCrackDataService::getLatestAcceleration);
                    break;
                case SOIL_MOISTURE:
                    monitorTypeMap.put(typeEnum.getMonitorType(), slopeSoilDataService::getLatestSoilMoisture);
                    break;
                case SOIL_TEMPERATURE:
                    monitorTypeMap.put(typeEnum.getMonitorType(), slopeSoilDataService::getLatestSoilTemperature);
                    break;
                case FENCE_TILT:
                    monitorTypeMap.put(typeEnum.getMonitorType(), slopeFencenetDataService::getLatestFencenetTilt);
                    break;
                case FENCE_ACCELERATION:
                    monitorTypeMap.put(typeEnum.getMonitorType(), slopeFencenetDataService::getLatestFencenetAcceleration);
                    break;
                default:
                    // 不做处理
                    break;
            }
        }
    }

    @PostConstruct
    public void init2() {
        monitorTypeSetMap = new HashMap<>();
        for (MonitorTypeEnum typeEnum : MonitorTypeEnum.values()) {
            switch (typeEnum) {
                case CRACK:
                    monitorTypeSetMap.put(typeEnum.getMonitorType(), slopeCrackDataService::getLatestCrackDataSet);
                    break;
                case STRUCTURE_TILT:
                    monitorTypeSetMap.put(typeEnum.getMonitorType(), slopeCrackDataService::getLatestTiltData);
                    break;
                case RAINFALL:
                    monitorTypeSetMap.put(typeEnum.getMonitorType(), slopeWeatherDataService::getLatestRainfall);
                    break;
                case TEMPERATURE:
                    monitorTypeSetMap.put(typeEnum.getMonitorType(), slopeWeatherDataService::getLatestTemperature);
                    break;
                case ACCELERATION:
                    monitorTypeSetMap.put(typeEnum.getMonitorType(), slopeCrackDataService::getLatestAcceleration);
                    break;
                case SOIL_MOISTURE:
                    monitorTypeSetMap.put(typeEnum.getMonitorType(), slopeSoilDataService::getLatestSoilMoisture);
                    break;
                case SOIL_TEMPERATURE:
                    monitorTypeSetMap.put(typeEnum.getMonitorType(), slopeSoilDataService::getLatestSoilTemperature);
                    break;
                case FENCE_TILT:
                    monitorTypeSetMap.put(typeEnum.getMonitorType(), slopeFencenetDataService::getLatestFencenetTilt);
                    break;
                case FENCE_ACCELERATION:
                    monitorTypeSetMap.put(typeEnum.getMonitorType(), slopeFencenetDataService::getLatestFencenetAcceleration);
                    break;
                default:
                    // 不做处理
                    break;
            }
        }
    }

    @Override
    public Map<String, Object> getMonitorData(String monitorType, String deviceSn, Date startTime, Date endTime) {
        Map<String, Object> result = new HashMap<>();
        List<Map<String, Object>> dataList = new ArrayList<>();

        switch (monitorType) {
            case "2": // 裂缝传感器
                SlopeCrackData crackQuery = new SlopeCrackData();
                crackQuery.setDeviceSn(deviceSn);
                crackQuery.setStartTime(startTime);
                crackQuery.setEndTime(endTime);
                List<SlopeCrackData> crackList = slopeCrackDataService.selectSlopeCrackDataList(crackQuery);
                for (SlopeCrackData crack : crackList) {
                    Map<String, Object> map = new HashMap<>();
                    // 裂缝累计变化量
                    if (crack.getCrackChange() != null) map.put("crackChange", crack.getCrackChange());
                    if (crack.getCreateTime() != null) map.put("time", crack.getCreateTime());
                    dataList.add(map);
                }
                break;

            case "7": // 支挡结构物倾斜传感器
                SlopeCrackData tilt = new SlopeCrackData();
                tilt.setDeviceSn(deviceSn);
                tilt.setStartTime(startTime);
                tilt.setEndTime(endTime);
                tilt.setCrackOrAngle(1);
                List<SlopeCrackData> tiltList = slopeCrackDataService.selectSlopeQingXieDataList(tilt);
                for (SlopeCrackData crack : tiltList) {
                    Map<String, Object> map = new HashMap<>();
                    // 支挡结构物倾斜
                    if (crack.getXTiltAngle() != null) map.put("xTiltAngle", crack.getXTiltAngle());
                    if (crack.getYTiltAngle() != null) map.put("yTiltAngle", crack.getYTiltAngle());
                    if (crack.getZTiltAngle() != null) map.put("zTiltAngle", crack.getZTiltAngle());
                    if (crack.getXyTiltAngle() != null) map.put("xyTiltAngle", crack.getXyTiltAngle());
                    if (crack.getAzimuth() != null) map.put("azimuth", crack.getAzimuth());
                    if (crack.getCreateTime() != null) map.put("time", crack.getCreateTime());
                    dataList.add(map);
                }
                break;

            case "15": // 加速度传感器
                SlopeCrackData acc = new SlopeCrackData();
                acc.setDeviceSn(deviceSn);
                acc.setStartTime(startTime);
                acc.setEndTime(endTime);
                List<SlopeCrackData> accelList = slopeCrackDataMapper.selectSlopeCrackDatasList(acc);
                for (SlopeCrackData crack : accelList) {
                    Map<String, Object> map = new HashMap<>();
                    // 加速度
                    if (crack.getXAcceleration() != null) map.put("xAcceleration", crack.getXAcceleration());
                    if (crack.getYAcceleration() != null) map.put("yAcceleration", crack.getYAcceleration());
                    if (crack.getZAcceleration() != null) map.put("zAcceleration", crack.getZAcceleration());
                    if (crack.getCreateTime() != null) map.put("time", crack.getCreateTime());
                    dataList.add(map);
                }
                break;

            case "11": // 气象降雨量传感器
                SlopeWeatherData rain = new SlopeWeatherData();
                rain.setDeviceSn(deviceSn);
                rain.setStartTime(startTime);
                rain.setEndTime(endTime);
                List<SlopeWeatherData> rainList = slopeWeatherDataService.selectSlopeWeatherDataList(rain);
                for (SlopeWeatherData weather : rainList) {
                    Map<String, Object> map = new HashMap<>();
                    // 降雨量
                    if (weather.getCumulativeRainfall() != null) map.put("cumulativeRainfall", weather.getCumulativeRainfall());
                    if (weather.getDailyRainfall() != null) map.put("dailyRainfall", weather.getDailyRainfall());
                    if (weather.getHourlyRainfall() != null) map.put("hourlyRainfall", weather.getHourlyRainfall());
                    if (weather.getCreateTime() != null) map.put("time", weather.getCreateTime());
                    dataList.add(map);
                }
                break;

            case "12": // 气温传感器
                SlopeWeatherData temp = new SlopeWeatherData();
                temp.setDeviceSn(deviceSn);
                temp.setStartTime(startTime);
                temp.setEndTime(endTime);
                List<SlopeWeatherData> tempList = slopeWeatherDataService.selectSlopeWeatherDataList(temp);
                for (SlopeWeatherData weather : tempList) {
                    Map<String, Object> map = new HashMap<>();
                    // 气温
                    if (weather.getTemperature() != null) map.put("temperature", weather.getTemperature());
                    if (weather.getCreateTime() != null) map.put("time", weather.getCreateTime());
                    dataList.add(map);
                }
                break;

            case "20": // 土壤含水率传感器
                SlopeSoilData soilMoisture = new SlopeSoilData();
                soilMoisture.setDeviceSn(deviceSn);
                soilMoisture.setStartTime(startTime);
                soilMoisture.setEndTime(endTime);
                List<SlopeSoilData> soilMoistureList = slopeSoilDataService.selectSlopeSoilDataList(soilMoisture);
                for (SlopeSoilData soil : soilMoistureList) {
                    Map<String, Object> map = new HashMap<>();
                    // 土壤含水率
                    if (soil.getSoilMoistureRatio0() != null) map.put("soilMoisture0", soil.getSoilMoistureRatio0());
                    if (soil.getSoilMoistureRatio1() != null) map.put("soilMoisture1", soil.getSoilMoistureRatio1());
                    if (soil.getSoilMoistureRatio2() != null) map.put("soilMoisture2", soil.getSoilMoistureRatio2());
                    if (soil.getSoilMoistureRatio3() != null) map.put("soilMoisture3", soil.getSoilMoistureRatio3());
                    if (soil.getSoilMoistureRatio4() != null) map.put("soilMoisture4", soil.getSoilMoistureRatio4());
                    if (soil.getCreateTime() != null) map.put("time", soil.getCreateTime());
                    dataList.add(map);
                }
                break;

            case "21": // 土壤温度传感器
                SlopeSoilData soilTemp = new SlopeSoilData();
                soilTemp.setDeviceSn(deviceSn);
                soilTemp.setStartTime(startTime);
                soilTemp.setEndTime(endTime);
                List<SlopeSoilData> soilTempList = slopeSoilDataService.selectSlopeSoilDataList(soilTemp);
                for (SlopeSoilData soil : soilTempList) {
                    Map<String, Object> map = new HashMap<>();
                    // 土壤温度
                    if (soil.getSoilTemperature0() != null) map.put("soilTemperature0", soil.getSoilTemperature0());
                    if (soil.getSoilTemperature1() != null) map.put("soilTemperature1", soil.getSoilTemperature1());
                    if (soil.getSoilTemperature2() != null) map.put("soilTemperature2", soil.getSoilTemperature2());
                    if (soil.getSoilTemperature3() != null) map.put("soilTemperature3", soil.getSoilTemperature3());
                    if (soil.getSoilTemperature4() != null) map.put("soilTemperature4", soil.getSoilTemperature4());
                    if (soil.getCreateTime() != null) map.put("time", soil.getCreateTime());
                    dataList.add(map);
                }
                break;

            case "23": // 防护倾角传感器
                SlopeFencenetData fenceTilt = new SlopeFencenetData();
                fenceTilt.setDeviceSn(deviceSn);
                fenceTilt.setStartTime(startTime);
                fenceTilt.setEndTime(endTime);
                List<SlopeFencenetData> fenceTiltList = slopeFencenetDataService.selectSlopeFencenetDataList(fenceTilt);
                for (SlopeFencenetData fence : fenceTiltList) {
                    Map<String, Object> map = new HashMap<>();
                    // 防护倾角
                    if (fence.getXTiltAngle() != null) map.put("xTiltAngle", fence.getXTiltAngle());
                    if (fence.getYTiltAngle() != null) map.put("yTiltAngle", fence.getYTiltAngle());
                    if (fence.getZTiltAngle() != null) map.put("zTiltAngle", fence.getZTiltAngle());
                    if (fence.getCreateTime() != null) map.put("time", fence.getCreateTime());
                    dataList.add(map);
                }
                break;

            case "24": // 防护加速度传感器
                SlopeFencenetData fenceAcc = new SlopeFencenetData();
                fenceAcc.setDeviceSn(deviceSn);
                fenceAcc.setStartTime(startTime);
                fenceAcc.setEndTime(endTime);
                List<SlopeFencenetData> fenceAccelList = slopeFencenetDataService.selectSlopeFencenetDataList(fenceAcc);
                for (SlopeFencenetData fence : fenceAccelList) {
                    Map<String, Object> map = new HashMap<>();
                    // 防护加速度
                    if (fence.getXAcceleration() != null) map.put("xAcceleration", fence.getXAcceleration());
                    if (fence.getYAcceleration() != null) map.put("yAcceleration", fence.getYAcceleration());
                    if (fence.getZAcceleration() != null) map.put("zAcceleration", fence.getZAcceleration());
                    if (fence.getCreateTime() != null) map.put("time", fence.getCreateTime());
                    dataList.add(map);
                }
                break;

            default:
                result.put("error", "未知的监测类型：" + monitorType);
                return result;
        }

        result.put("data", dataList);
        return result;
    }


    @Override
    public Map<String, Object> getAllSlopeWarningInfo(String slopeCode) {
        Map<String, Object> result = new HashMap<>();

        // 查找边坡基本信息
        SlopeInfo slopeInfo = new SlopeInfo();
        slopeInfo.setSlopeCode(slopeCode);
        List<SlopeInfo> list = slopeInfoServiceImpl.selectSlopeInfoList(slopeInfo);
        if (list == null || list.isEmpty()) {
            result.put("code", 404);
            result.put("msg", "未找到边坡信息");
            return result;
        }
        String slopeName = list.get(0).getSlopeName();

        // 查询报警信息
        SlopeWarningInfo slopeWarningInfo = new SlopeWarningInfo();
        slopeWarningInfo.setSlopeName(slopeName);
        List<SlopeWarningInfo> warningList = slopeWarningInfoServiceImpl.selectSlopeWarningInfoList(slopeWarningInfo);
        if (warningList == null || warningList.isEmpty()) {
            result.put("code", 0);
            result.put("slopeName", slopeName);
            result.put("slopeCode", slopeCode);
            result.put("data", Collections.singletonMap("alarmInfo", new ArrayList<>()));
            return result;
        }

        // 1. 按设备分组，只保留每个设备最新的一条记录
        Map<String, SlopeWarningInfo> latestWarningMap = new HashMap<>();
        for (SlopeWarningInfo w : warningList) {
            String deviceSn = w.getDeviceSn();
            if (deviceSn == null) continue;
            SlopeWarningInfo existing = latestWarningMap.get(deviceSn);
            if (existing == null ||
                    (w.getWarningTime() != null && existing.getWarningTime() != null
                            && w.getWarningTime().after(existing.getWarningTime()))) {
                latestWarningMap.put(deviceSn, w);
            }
        }

        // 2. 封装 alarmInfoList
        List<Map<String, Object>> alarmInfoList = new ArrayList<>();
        for (SlopeWarningInfo w : latestWarningMap.values()) {
            String deviceName = "";
            SlopeDeviceInfo deviceInfo = new SlopeDeviceInfo();
            deviceInfo.setDeviceSn(w.getDeviceSn());
            List<SlopeDeviceInfo> l = slopeDeviceInfoServiceImpl.selectSlopeDeviceInfoList(deviceInfo);
            if (l != null && !l.isEmpty()) {
                deviceName = l.get(0).getDeviceName();
            }

            Map<String, Object> alarmMap = new HashMap<>();
            alarmMap.put("deviceName", deviceName);
            alarmMap.put("sn", w.getDeviceSn());
            alarmMap.put("time", w.getWarningTime() != null ? w.getWarningTime().getTime() : null);
            alarmMap.put("monitorType", w.getMonitorType());
            if (w.getChangeRate() != 0.0) {
                alarmMap.put("changeRate", w.getChangeRate());
            }
            if (w.getCumulativeValue() != 0.0) {
                alarmMap.put("cumulativeValue", w.getCumulativeValue());
            }
            alarmInfoList.add(alarmMap);
        }

        // 3. 封装最终返回结果
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("alarmInfo", alarmInfoList);

        result.put("code", 0);
        result.put("slopeName", slopeName);
        result.put("slopeCode", slopeCode);
        result.put("data", dataMap);

        return result;
    }


    @Override
    public Map<String, Object> getAllSlopeData(String slopeCode) {
        SlopeMonitorpoints smp = new SlopeMonitorpoints();
        smp.setSlopeCode(slopeCode);
        List<SlopeMonitorpoints> monitorPoints = slopeMonitorpointsService
                .selectSlopeMonitorpointsList(smp);

        Map<String, Object> result = new HashMap<>();
        // 临时 Map 用于合并相同 monitorid
        Map<String, Map<String, Object>> tempMap = new HashMap<>();

        for (SlopeMonitorpoints mp : monitorPoints) {
            String monitorId = mp.getMonitorId();
            String deviceId = mp.getDeviceId();
            String monitorType = mp.getMonitoringType();

            SlopeDeviceInfo sdi = new SlopeDeviceInfo();
            sdi.setSensorId(deviceId);

            List<SlopeDeviceInfo> sdiList = slopeDeviceInfoService.selectSlopeDeviceInfoList(sdi);
            String deviceSn = (sdiList != null && !sdiList.isEmpty()) ? sdiList.get(0).getDeviceSn() : null;

            DataFetcher fetcher = monitorTypeMap.get(monitorType);
            if (fetcher == null || deviceSn == null) {
                System.out.println("跳过未处理的监测类型: " + monitorType + ", DeviceID: " + deviceId);
                continue;
            }

            Object dto = fetcher.fetch(deviceSn);

            // 这里计算时间
            String updateTime = String.valueOf(getUpdateTime(dto));

            // 打印日志
            System.out.println("MonitorID: " + monitorId +
                    ", DeviceID: " + deviceId +
                    ", DeviceSN: " + deviceSn +
                    ", MonitorType: " + monitorType +
                    ", DTO: " + dto);

            // 构建单条数据 Map
            Map<String, Object> dataMap = new LinkedHashMap<>();
            dataMap.put("sn", deviceSn);
            dataMap.put("monitorType", monitorType);
            dataMap.put("time", updateTime);  // ✅ 每条数据加时间
            if (dto != null) {
                Map<String, Object> dtoMap = dtoToMap(dto);
                dtoMap.forEach(dataMap::put);
            }

            // 合并到 tempMap
            Map<String, Object> dataItem;
            if (tempMap.containsKey(monitorId)) {
                dataItem = tempMap.get(monitorId);
            } else {
                dataItem = new HashMap<>();
                dataItem.put("monitorid", monitorId);
                dataItem.put("time", updateTime); // 这里保留汇总时间
                dataItem.put("data", new ArrayList<Map<String, Object>>());
                tempMap.put(monitorId, dataItem);
            }

            List<Map<String, Object>> dataList = (List<Map<String, Object>>) dataItem.get("data");
            dataList.add(dataMap);
        }

        // 转成列表
        List<Map<String, Object>> datas = new ArrayList<>(tempMap.values());

        result.put("code", 0);
        result.put("dataType", 1);
        result.put("slopeCode", slopeCode);
        result.put("datas", datas);

        return result;
    }

    @Override
    public Map<String, Object> getAllSlopeDataSet(String slopeCode) {
        SlopeMonitorpoints smp = new SlopeMonitorpoints();
        smp.setSlopeCode(slopeCode);
        List<SlopeMonitorpoints> monitorPoints = slopeMonitorpointsService
                .selectSlopeMonitorpointsList(smp);

        Map<String, Object> result = new HashMap<>();
        // 临时 Map 用于合并相同 monitorid
        Map<String, Map<String, Object>> tempMap = new HashMap<>();

        for (SlopeMonitorpoints mp : monitorPoints) {
            String monitorId = mp.getMonitorId();
            String deviceId = mp.getDeviceId();
            String monitorType = mp.getMonitoringType();

            SlopeDeviceInfo sdi = new SlopeDeviceInfo();
            sdi.setSensorId(deviceId);

            List<SlopeDeviceInfo> sdiList = slopeDeviceInfoService.selectSlopeDeviceInfoList(sdi);
            String deviceSn = (sdiList != null && !sdiList.isEmpty()) ? sdiList.get(0).getDeviceSn() : null;

            DataFetcher fetcher = monitorTypeSetMap.get(monitorType);
            if (fetcher == null || deviceSn == null) {
                System.out.println("跳过未处理的监测类型: " + monitorType + ", DeviceID: " + deviceId);
                continue;
            }

            Object dto = fetcher.fetch(deviceSn);

            // 这里计算时间
            String updateTime = String.valueOf(getUpdateTime(dto));

            // 打印日志
            System.out.println("MonitorID: " + monitorId +
                    ", DeviceID: " + deviceId +
                    ", DeviceSN: " + deviceSn +
                    ", MonitorType: " + monitorType +
                    ", DTO: " + dto);

            // 构建单条数据 Map
            Map<String, Object> dataMap = new LinkedHashMap<>();
            dataMap.put("sn", deviceSn);
            dataMap.put("monitorType", monitorType);
            dataMap.put("time", updateTime);  // ✅ 每条数据加时间
            if (dto != null) {
                Map<String, Object> dtoMap = dtoToMap(dto);
                dataMap.putAll(dtoMap);
            }

            // 合并到 tempMap
            Map<String, Object> dataItem;
            if (tempMap.containsKey(monitorId)) {
                dataItem = tempMap.get(monitorId);
            } else {
                dataItem = new HashMap<>();
                dataItem.put("monitorid", monitorId);
                dataItem.put("time", updateTime); // 这里保留汇总时间
                dataItem.put("data", new ArrayList<Map<String, Object>>());
                tempMap.put(monitorId, dataItem);
            }

            List<Map<String, Object>> dataList = (List<Map<String, Object>>) dataItem.get("data");
            dataList.add(dataMap);
        }

        // 转成列表
        List<Map<String, Object>> datas = new ArrayList<>(tempMap.values());

        result.put("code", 0);
        result.put("dataType", 1);
        result.put("slopeCode", slopeCode);
        result.put("datas", datas);

        return result;
    }


    /**
     * 统一获取 DTO 的更新时间
     */
    private Date getUpdateTime(Object dto) {
        if (dto == null) return null;
        if (dto instanceof SlopeCrackData) return ((SlopeCrackData) dto).getUpdateTime();
        if (dto instanceof SlopeWeatherData) return ((SlopeWeatherData) dto).getUpdateTime();
        if (dto instanceof SlopeSoilData) return ((SlopeSoilData) dto).getUpdateTime();
        if (dto instanceof SlopeFencenetData) return ((SlopeFencenetData) dto).getUpdateTime();
        return null;
    }

    /**
     * 将 DTO 转为 Map，只取对应监测类型的字段
     */
    private Map<String, Object> dtoToMap(Object dto) {
        Map<String, Object> map = new HashMap<>();
        if (dto == null) return map;

        if (dto instanceof SlopeCrackData crack) {
            // 裂缝累计变化量
            if (crack.getCrackChange() != null) map.put("crackChange", crack.getCrackChange());
            if (crack.getCrackChangeRate() != null) {
                BigDecimal rate = BigDecimal.valueOf(crack.getCrackChangeRate())
                        .setScale(2, RoundingMode.HALF_UP);
                map.put("crackChangeRate", rate);
            }

            // todo 裂缝变化率计算

            // 支挡结构物倾斜
            if (crack.getXTiltAngle() != null) map.put("xTiltAngle", crack.getXTiltAngle());
            if (crack.getYTiltAngle() != null) map.put("yTiltAngle", crack.getYTiltAngle());
            if (crack.getZTiltAngle() != null) map.put("zTiltAngle", crack.getZTiltAngle());
            if (crack.getXyTiltAngle() != null) map.put("xyTiltAngle", crack.getXyTiltAngle());
            if (crack.getAzimuth() != null) map.put("azimuth", crack.getAzimuth());

            // 加速度
            if (crack.getXAcceleration() != null) map.put("xAcceleration", crack.getXAcceleration());
            if (crack.getYAcceleration() != null) map.put("yAcceleration", crack.getYAcceleration());
            if (crack.getZAcceleration() != null) map.put("zAcceleration", crack.getZAcceleration());

        } else if (dto instanceof SlopeWeatherData weather) {
            // 降雨量
            if (weather.getCumulativeRainfall() != null) map.put("cumulativeRainfall", weather.getCumulativeRainfall());
            if (weather.getDailyRainfall() != null) map.put("dailyRainfall", weather.getDailyRainfall());
            if (weather.getHourlyRainfall() != null) map.put("hourlyRainfall", weather.getHourlyRainfall());

            // 气温
            if (weather.getTemperature() != null) map.put("temperature", weather.getTemperature());

        } else if (dto instanceof SlopeSoilData soil) {
            // 土壤含水率
            if (soil.getSoilMoistureRatio0() != null) map.put("soilMoisture0", soil.getSoilMoistureRatio0());
            if (soil.getSoilMoistureRatio1() != null) map.put("soilMoisture1", soil.getSoilMoistureRatio1());
            if (soil.getSoilMoistureRatio2() != null) map.put("soilMoisture2", soil.getSoilMoistureRatio2());
            if (soil.getSoilMoistureRatio3() != null) map.put("soilMoisture3", soil.getSoilMoistureRatio3());
            if (soil.getSoilMoistureRatio4() != null) map.put("soilMoisture4", soil.getSoilMoistureRatio4());

            // 土壤温度
            if (soil.getSoilTemperature0() != null) map.put("soilTemperature0", soil.getSoilTemperature0());
            if (soil.getSoilTemperature1() != null) map.put("soilTemperature1", soil.getSoilTemperature1());
            if (soil.getSoilTemperature2() != null) map.put("soilTemperature2", soil.getSoilTemperature2());
            if (soil.getSoilTemperature3() != null) map.put("soilTemperature3", soil.getSoilTemperature3());
            if (soil.getSoilTemperature4() != null) map.put("soilTemperature4", soil.getSoilTemperature4());

        } else if (dto instanceof SlopeFencenetData fence) {
            // 防护倾角
            if (fence.getXTiltAngle() != null) map.put("xTiltAngle", fence.getXTiltAngle());
            if (fence.getYTiltAngle() != null) map.put("yTiltAngle", fence.getYTiltAngle());
            if (fence.getZTiltAngle() != null) map.put("zTiltAngle", fence.getZTiltAngle());

            // 防护加速度
            if (fence.getXAcceleration() != null) map.put("xAcceleration", fence.getXAcceleration());
            if (fence.getYAcceleration() != null) map.put("yAcceleration", fence.getYAcceleration());
            if (fence.getZAcceleration() != null) map.put("zAcceleration", fence.getZAcceleration());
        }

        return map;
    }


    @FunctionalInterface
    interface DataFetcher {
        Object fetch(String deviceSn);
    }


}
